package com.ouyeel.cw.controller;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.google.common.base.CaseFormat;
import com.google.common.base.Converter;
import com.ouyeel.cw.model.Config;
import com.ouyeel.cw.model.FieldBean;
import com.ouyeel.cw.model.TableInfo;
import com.ouyeel.cw.util.CommonUtils;
import com.ouyeel.cw.util.Generator;
import com.ouyeel.cw.util.SqlUtils;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ListView;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.AnchorPane;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.sql.Connection;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

/**
 * @author song xj
 * @version 1.0
 * @create 2020-06-29 20:28
 * @copyright
 **/
@Slf4j
public class MainController {
    private Stage stage;
    private DataSourceConfig dataSourceConfig;
    private String doTableName;
    @FXML
    private AnchorPane pane;
    @FXML
    private TextArea content;
    @FXML
    private TextField txtTableName;
    @FXML
    private TextField txtTablePk;
    @FXML
    private TextField txtTableComment;
    @FXML
    private TextField txtDbHost;
    @FXML
    private TextField txtDbName;
    @FXML
    private TextField txtDbRoot;
    @FXML
    private TextField txtDbPwd;
    @FXML
    private TextField txtEntity;
    @FXML
    private TextField txtPackage;
    @FXML
    private TextField txtSrc;
    @FXML
    private ListView lvTables;
    @FXML
    private CheckBox chbCreateXml;
    @FXML
    private CheckBox chbCreateController;
    @FXML
    private CheckBox chbCreateService;


    private Stage getStage() {
        if (stage == null) {
            stage = (Stage) pane.getScene().getWindow();
        }
        return stage;
    }

    private DataSourceConfig getDataSourceConfig() throws Exception {
        if (ObjectUtil.isEmpty(txtDbHost.getText().trim())
                || ObjectUtil.isEmpty(txtDbName.getText().trim())
                || ObjectUtil.isEmpty(txtDbRoot.getText().trim())
                || ObjectUtil.isEmpty(txtDbPwd.getText().trim())) {
            CommonUtils.alertErr("请完善数据库连接信息");
            return null;
        }
        dataSourceConfig = null;
        dataSourceConfig = new DataSourceConfig();
        dataSourceConfig.setUrl("jdbc:mysql://" + txtDbHost.getText().trim() + "/" + txtDbName.getText().trim() + "?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL");
        dataSourceConfig.setDriverName("com.mysql.cj.jdbc.Driver");
        dataSourceConfig.setUsername(txtDbRoot.getText().trim());
        dataSourceConfig.setPassword(txtDbPwd.getText().trim());
//        dataSourceConfig.setSchemaName("dorado_test");
//        dataSourceConfig.setDbType(DbType.MYSQL);
        return dataSourceConfig;
    }

    @FXML
    public void dbReset() {
        reset();
    }

    @FXML
    public void build() {
        if (ObjectUtil.isEmpty(txtEntity.getText().trim()) || ObjectUtil.isEmpty(txtPackage.getText().trim()) || ObjectUtil.isEmpty(txtSrc.getText().trim())) {
            CommonUtils.alertErr("请完善实体信息");
            return;
        }
        if (ObjectUtil.isEmpty(doTableName)) {
            CommonUtils.alertErr("请输入有效实体名称");
            return;
        }
        try {
            Config config = new Config();
            config.setDataSourceConfig(getDataSourceConfig());
            config.setCreateController(chbCreateController.isSelected());
            config.setCreateService(chbCreateService.isSelected());
            config.setCreateServiceImpl(chbCreateService.isSelected());
            config.setCreateXml(chbCreateXml.isSelected());
            config.setTableName(doTableName);
            config.setEntityName(txtEntity.getText().trim());
            config.setProjectPath(txtSrc.getText().trim());
            config.setPackageName(txtPackage.getText().trim());
            Task<String> task1 = new Task<String>() {
                @Override
                protected String call() throws Exception {
                    Generator.build(config);
                    return "call";
                }

                @Override
                protected void succeeded() {
                    super.succeeded();
                    CommonUtils.alertInfo("success");
                }

                @Override
                protected void failed() {
                    super.failed();
                    CommonUtils.alertInfo("fail");
                }
            };
            new Thread(task1).start();
//            CommonUtils.alertInfo("success");
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            CommonUtils.alertErr(e.getMessage());
        }
    }

    @FXML
    public void getDbConection() {
        try {
            DataSourceConfig db = getDataSourceConfig();
            Connection conn = db.getConn();
            ResultSet tables = conn.getMetaData().getTables(txtDbName.getText().trim(), null, null, new String[]{"TABLE"});
            List<String> list = new ArrayList<>();
            while (tables.next()) {
                list.add(tables.getString("TABLE_NAME"));
            }
            conn.close();
            ObservableList<String> strings = FXCollections.observableArrayList(list);
            lvTables.setItems(null);
            lvTables.setItems(strings);
            lvTables.getSelectionModel().selectedItemProperty().addListener(new ChangeListener() {
                @Override
                public void changed(ObservableValue observable, Object oldValue, Object newValue) {
                    doTableName = newValue.toString();
                    Converter<String, String> converter = CaseFormat.LOWER_UNDERSCORE.converterTo(CaseFormat.LOWER_CAMEL);
                    txtEntity.setText(converter.convert(doTableName));
                }
            });
        } catch (Exception e) {
            CommonUtils.alertErr(e.getMessage());
        }
    }

    @FXML
    public void fileSelectClick(ActionEvent event) {
        if (ObjectUtil.isEmpty(txtTableComment.getText().trim()) || ObjectUtil.isEmpty(txtTableName.getText().trim()) || ObjectUtil.isEmpty(txtTablePk.getText().trim())) {
            CommonUtils.alertErr("请完善表名/主键/表注释信息");
            return;
        }
        FileChooser fileChooser = new FileChooser();
        fileChooser.setTitle("Open Resource File");
        File file = fileChooser.showOpenDialog(getStage());
        if (ObjectUtil.isNotEmpty(file)) {
            if (file.getName().endsWith(".xlsx") || file.getName().endsWith(".xls")) {
                Task<String> task = new Task<String>() {
                    @Override
                    protected String call() throws Exception {
                        List<FieldBean> fields = SqlUtils.getFieldsFromExcle(file.toURI().getPath());
                        TableInfo tableInfo = new TableInfo(txtTableName.getText().trim(), txtTablePk.getText().trim(), txtTableComment.getText().trim());
                        String sql = SqlUtils.buildSql(fields, tableInfo);
                        updateContentText(sql);
                        return sql;
                    }
                };
                new Thread(task).start();
                this.updateContentText("加载中...");
            } else {
                CommonUtils.alertErr("请选择Excel文件");
            }
        }
    }

    @FXML
    public void clearClick() {
        content.clear();
    }

    @FXML
    public void selectAllClick() {
        content.selectAll();
        content.copy();
    }

    private void updateContentText(String text) {
        content.clear();
        content.appendText(text);
    }

    private void reset() {
        dataSourceConfig = null;
        lvTables.getItems().clear();
        doTableName = "";
        txtDbHost.clear();
        txtDbPwd.clear();
        txtDbRoot.clear();
        txtSrc.clear();
        txtPackage.clear();
        txtEntity.clear();
    }
}
